package com.tfleo.mealssenger;

import com.github.ignition.core.widgets.RemoteImageView;
import com.tfleo.mealssenger.R;
import com.tfleo.mealssenger.utility.ImageTools;
import com.tfleo.mealssenger.utility.NetworkTools;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.Typeface;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.provider.MediaStore.Images.Media;
import android.provider.Settings.Secure;
import android.text.method.PasswordTransformationMethod;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.TextView;
import android.widget.Toast;

/**
 * Edit user's profile.
 * 
 * @author Theodore Felix Leo
 *
 */
public class EditProfileActivity extends Activity {
	private static final String UPLOAD_URL = 
			Main.SERVER_URL + "image_upload.php?op=0"; //op=0 store in 'SERVER/img/user/'
	private static final int CAMERA_REQUEST = 1;
	
	private ImageView vProfileImage;
	private RemoteImageView vDefaultProfileImage;
	private EditText vNameEntry;
	private Button vSubmitBtn;
	private TextView vRestoreImage;
	private TextView vChangePassword;
	
	private Context mContext;
	private LayoutInflater mInflater;
	
	private SharedPreferences mUserData;
	private SharedPreferences.Editor mPrefEditor;
	
	private File mImageDir;
	private File mCurImageDir;
	private File mRoot;
	private Uri mOutputFileUri;
	private Bitmap mPhoto;
	
	private int mId;
	private String mName;
	private String mImageUrl;
	
	// These are used in case filename uploaded set to be the same with local filename
	// Now: image filename in server is [ID].jpg
	private String mImageFileName;
	//private String mCurImageFileName;
	
	private boolean mNewImage = false;
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
	    setContentView(R.layout.edit_profile_layout);
	    mContext = this;
	    mInflater = (LayoutInflater) getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
	    
	    mUserData = getSharedPreferences(Main.USER_DATA, MODE_PRIVATE);
	    mPrefEditor = mUserData.edit();
	    mId = mUserData.getInt(Main.USER_ID, 0);
	    mName = mUserData.getString(Main.USER_NAME, "");
	    mImageUrl = Main.SERVER_URL + "img/user/" + mUserData.getString(Main.USER_IMAGE, "");
	    
	    // Root directory to store image
	    mRoot = new File(Environment.getExternalStorageDirectory() + File.separator 
	    		+ "Mealssenger" + File.separator);
	    mRoot.mkdirs();
	    
        // Filename for image using random number
	    Random filename = new Random();
        mImageDir = new File(mRoot, Integer.toString(filename.nextInt()) + ".jpg");
        mOutputFileUri = Uri.fromFile(mImageDir);
	
        vNameEntry = (EditText) findViewById(R.id.name_entry);
        
        vChangePassword = (TextView) findViewById(R.id.change_password);
        vChangePassword.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				buildDialog();
			}
	    	
	    });
        
        vRestoreImage = (TextView) findViewById(R.id.restore_default);
	    vRestoreImage.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				vDefaultProfileImage.setVisibility(View.VISIBLE);
				vProfileImage.setVisibility(View.GONE);
				vRestoreImage.setVisibility(View.GONE);
				mNewImage = false;
			}
	    	
	    });
	    
        vDefaultProfileImage = (RemoteImageView) findViewById(R.id.image_default);
        vDefaultProfileImage.setImageUrl(mImageUrl);
        vDefaultProfileImage.loadImage();
        vDefaultProfileImage.setOnClickListener(new OnClickListener() {
	    	public void onClick(View v) {
	    		vDefaultProfileImage.setVisibility(View.GONE);
	    		vProfileImage.setImageResource(R.drawable.profile_pic);
	    		vProfileImage.setVisibility(View.VISIBLE);
	    		vRestoreImage.setVisibility(View.VISIBLE);
	    		if(mPhoto != null) {
	    			mPhoto.recycle();
	    			System.gc(); //TODO: see whether this can be removed
	    		}
	    		
	    		Random filename = new Random();
	    		mImageFileName = Integer.toString(filename.nextInt()) + ".jpg";
	            mImageDir = new File(mRoot, mImageFileName);
	            mOutputFileUri = Uri.fromFile(mImageDir);
	    		
	    		System.gc(); //TODO: see whether this can be removed
	    		Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); 
	    		i.putExtra(MediaStore.EXTRA_OUTPUT, mOutputFileUri);
	    		startActivityForResult(i, CAMERA_REQUEST); 
	    	}
	    });
        
	    vProfileImage = (ImageView) findViewById(R.id.image);
	    vProfileImage.setOnClickListener(new OnClickListener() {
	    	public void onClick(View v) {
	    		if(mPhoto != null) {
	    			mPhoto.recycle();
	    			System.gc(); //TODO: see whether this can be removed
	    		}
	    		
	    		Random filename = new Random();
	    		mImageFileName = Integer.toString(filename.nextInt()) + ".jpg";
	            mImageDir = new File(mRoot, mImageFileName);
	            mOutputFileUri = Uri.fromFile(mImageDir);
	    		
	    		System.gc(); //TODO: see whether this can be removed
	    		Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); 
	    		i.putExtra(MediaStore.EXTRA_OUTPUT, mOutputFileUri);
	    		startActivityForResult(i, CAMERA_REQUEST); 
	    	}
	    });
	    
	    vSubmitBtn = (Button) findViewById(R.id.submit);
	    vSubmitBtn.setOnClickListener(new OnClickListener() {
	    	public void onClick(View v) {	    	
				if((mName = vNameEntry.getText().toString()).trim().equals("")) {
					Toast.makeText(mContext, "Error: Please key in your user display name!", 
							Toast.LENGTH_SHORT).show();
					return;
				}
				
				SubmitTask task = new SubmitTask();
	    		task.execute(new String[] {mName});
	    	}
	    });
	    
	    if(!NetworkTools.isNetworkAvailable(mContext)) {
	    	Toast.makeText(getApplicationContext(),
					"Warning: Network is currently unavailable!", Toast.LENGTH_LONG).show();
	    }
	}
	
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {  
        if (requestCode == CAMERA_REQUEST) {  
        	if (resultCode == RESULT_OK) {
        		try {
        			System.gc();
        			//mPhoto.recycle();
        			getContentResolver().notifyChange(mOutputFileUri, null);       			
        			ImageTools.compress(getContentResolver(), mOutputFileUri, mImageDir);
        			
        			//Set thumbnail
        			mPhoto = Media.getBitmap(getContentResolver(), mOutputFileUri);
        			vProfileImage.setImageBitmap(mPhoto);
        			vProfileImage.setScaleType(ScaleType.CENTER_CROP);
    	            
        			mCurImageDir = mImageDir;
        			//mCurImageFileName = mImageFileName;
        			mNewImage = true;
    	        } catch(FileNotFoundException e) {
    	            e.printStackTrace();
    	        } catch(IOException e) {
    	            e.printStackTrace();
    	        } catch(Exception e) {
    	            e.printStackTrace();
    	        }
        		
            } else if (resultCode == RESULT_CANCELED) {
            	if(mNewImage) {
            		//Reuse last image if available
	            	mImageDir = mCurImageDir;
	            	//mImageFileName = mCurImageFileName;
	            	mOutputFileUri = Uri.fromFile(mImageDir);
	            	try {
	        			getContentResolver().notifyChange(mOutputFileUri, null);       			

	        			mPhoto = Media.getBitmap(getContentResolver(), mOutputFileUri);
	        			vProfileImage.setImageBitmap(mPhoto);
	        			vProfileImage.setScaleType(ScaleType.CENTER_CROP);
	    	            
	        			mCurImageDir = mImageDir;
	        			mNewImage = true;
	    	        } catch(FileNotFoundException e) {
	    	            e.printStackTrace();
	    	        } catch(IOException e) {
	    	            e.printStackTrace();
	    	        } catch(Exception e) {
	    	            e.printStackTrace();
	    	        }
            	}
            } else {
            	Toast.makeText(mContext, "Error: Failed to take picture!", Toast.LENGTH_SHORT).show();
            }
        }  
    } 
	
	private void buildDialog() {
		View layout = mInflater.inflate(R.layout.change_pass_dialog, null);
	    final EditText vOldPass = (EditText) layout.findViewById(R.id.old_pass_entry);
	    vOldPass.setTypeface(Typeface.DEFAULT);
	    vOldPass.setTransformationMethod(new PasswordTransformationMethod());
	    
	    final EditText vNewPass = (EditText) layout.findViewById(R.id.new_pass_entry);
	    vNewPass.setTypeface(Typeface.DEFAULT);
	    vNewPass.setTransformationMethod(new PasswordTransformationMethod());
	    
	    final EditText vConPass = (EditText) layout.findViewById(R.id.con_pass_entry);
	    vConPass.setTypeface(Typeface.DEFAULT);
	    vConPass.setTransformationMethod(new PasswordTransformationMethod());
	    
	    
	    //Building dialog
	    AlertDialog.Builder builder = new AlertDialog.Builder(this);
	    builder.setView(layout);
	    
	    builder.setPositiveButton("Submit", new DialogInterface.OnClickListener() {
	        public void onClick(DialogInterface dialog, int which) {
	        	String oldPass, newPass, conPass;
	        	if((oldPass = vOldPass.getText().toString().trim()).equals("")) {
	        		Toast.makeText(mContext, "Error: Empty field (Old password)!", Toast.LENGTH_SHORT).show();
	        		return;
	        	}
	        	if((newPass = vNewPass.getText().toString().trim()).equals("")) {
	        		Toast.makeText(mContext, "Error: Empty field (New password)!", Toast.LENGTH_SHORT).show();
	        		return;
	        	}
	        	if((conPass = vConPass.getText().toString().trim()).equals("")) {
	        		Toast.makeText(mContext, "Error: Empty field (Confirm password)!", Toast.LENGTH_SHORT).show();
	        		return;
	        	}
	        	if(conPass.compareTo(newPass) != 0) {
	        		Toast.makeText(mContext, "Error: New password mismatch!", Toast.LENGTH_SHORT).show();
	        		return;
	        	}
	        	
	        	ChangePassTask task = new ChangePassTask();
	            String[] data = new String[]{
	            		oldPass,
	            		newPass
	            };
	            task.execute(data);  
	        }
	    });
	    
	    builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
	        public void onClick(DialogInterface dialog, int which) {
	            dialog.dismiss();
	        }
	    });
	    
	    AlertDialog dialog = builder.create();
		dialog.setTitle("Change password");
		dialog.show();
		
		ViewGroup parent = (ViewGroup)layout.getParent();
		parent.setPadding(0, 0, 0, 1);
	}
	
	private boolean editUser(String name) {
		HttpClient httpclient = new DefaultHttpClient();
		HttpPost httppost = new HttpPost(Main.SERVER_URL + "edit_user.php?ch_name=1");
		String auth = Secure.getString(this.getContentResolver(), Secure.ANDROID_ID); //for authentication
		try {
			List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
			nameValuePairs.add(new BasicNameValuePair("id", Integer.toString(mId)));
			nameValuePairs.add(new BasicNameValuePair("name", name));
			nameValuePairs.add(new BasicNameValuePair("auth", auth));
			nameValuePairs.add(new BasicNameValuePair("has_image", Boolean.toString(mNewImage)));
			httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

			//Execute HTTP Post Request
			ResponseHandler<String> responseHandler = new BasicResponseHandler();
			String responseBody = httpclient.execute(httppost, responseHandler);
			JSONObject response = new JSONObject(responseBody);
			
			//Image file name in server is equal to its ID
			//TODO: Why not using same random file name?
			if(response.getInt("code") > 0) {
				if(mNewImage) {
					Log.i("EditProfileActivity", "Uploading picture " + response.getInt("code"));
					ImageTools.upload(mCurImageDir, UPLOAD_URL, Integer.toString(mId) + ".jpg");
				}
				return true;
			} else {
				return false;
			}
		} catch(JSONException e){
			e.printStackTrace();
		} catch(IOException e) {
			e.printStackTrace();
		} catch(Exception e) {
			e.printStackTrace();
		}
		
		return false;
	}
	
	private boolean changePass(String oldPass, String newPass) {
		HttpClient httpclient = new DefaultHttpClient();
		HttpPost httppost = new HttpPost(Main.SERVER_URL + "edit_user.php?ch_pass=1");
		String auth = Secure.getString(this.getContentResolver(), Secure.ANDROID_ID); //for authentication
		try {
			List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
			nameValuePairs.add(new BasicNameValuePair("id", Integer.toString(mId)));
			nameValuePairs.add(new BasicNameValuePair("old_pass", oldPass));
			nameValuePairs.add(new BasicNameValuePair("new_pass", newPass));
			nameValuePairs.add(new BasicNameValuePair("auth", auth));
			httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

			//Execute HTTP Post Request
			ResponseHandler<String> responseHandler = new BasicResponseHandler();
			String responseBody = httpclient.execute(httppost, responseHandler);
			JSONObject response = new JSONObject(responseBody);
		
			if(response.getInt("code") > 0) {
				mPrefEditor.putString(Main.TOKEN, newPass);
				mPrefEditor.commit();
				return true;
			} else {
				return false;
			}
		} catch(JSONException e){
			e.printStackTrace();
		} catch(IOException e) {
			e.printStackTrace();
		} catch(Exception e) {
			e.printStackTrace();
		}
		
		return false;
	}
	
	/**
	 * Asynchronous task to handle submission of data to server.
	 */
	private class SubmitTask extends AsyncTask<String, Void, Boolean> {
		@Override
		protected Boolean doInBackground(String... params) {
			return editUser(params[0]);
		}
		
		@Override
		protected void onPostExecute(Boolean result) {
			if(result) {
				mPhoto.recycle();
				setResult(RESULT_OK);
				finish();
			} else {
				Toast.makeText(getApplicationContext(), "Error: Failed to submit to server", 
						Toast.LENGTH_SHORT).show();
			}
	    }
	}
	
	private class ChangePassTask extends AsyncTask<String, Void, Boolean> {
		@Override
		protected Boolean doInBackground(String... params) {
			return changePass(params[0], params[1]);
		}
		
		@Override
		protected void onPostExecute(Boolean result) {
			if(result) {
				
			} else {
				Toast.makeText(getApplicationContext(), "Error: Failed to submit to server", 
						Toast.LENGTH_SHORT).show();
			}
	    }
		
	}
}
